package com.sprucetec.mcopenapi.api.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

import java.util.*;

public class SpecialStrUtil {
	/**
	 * 生成特征字符串
	 * 
	 * @param jsonObject
	 * @return
	 * @throws Exception
	 */
	public static String gen(JSONObject jsonObject, String salt) {
		StringBuilder builder = new StringBuilder();
		Map<String, List<String>> kvs = new HashMap<>();
		List<String> keys = new LinkedList<>();
		fetchLeafKV(jsonObject, kvs);

		keys.addAll(kvs.keySet());
		keys.remove("sign");
		Collections.sort(keys);
		Iterator<String> keyIter = keys.iterator();
		while (keyIter.hasNext()) {
			String key = (String) keyIter.next();
			String value = mergeValues(kvs.get(key));
			if (value != null && !"".equals(value))
				builder.append(key).append("=").append(value).append("&");
		}
		builder.deleteCharAt(builder.length() - 1);
		return builder.toString() + salt;
	}

	private static String mergeValues(List<String> vls) {
		String result = null;
		StringBuilder sbVls = new StringBuilder();
		if (vls != null && !vls.isEmpty()) {
			Collections.sort(vls);
			Iterator<String> iterator = vls.iterator();
			while (iterator.hasNext()) {
				Object obj = iterator.next();
				sbVls.append(obj).append("-");
			}
			if (sbVls.length() > 0)
				sbVls.deleteCharAt(sbVls.length() - 1);
			result = sbVls.toString();
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	private static void fetchLeafKV(JSONObject jsonObject, Map<String, List<String>> kvs) throws JSONException {
		Iterator<String> iterator = jsonObject.keySet().iterator();
		String key = null;
		while (iterator.hasNext()) {
			key = iterator.next();
			doFetchLeafKV(key, jsonObject.get(key), kvs);
		}
	}

	private static void doFetchLeafKV(String key, Object valObj, Map<String, List<String>> kvs) {
		if (valObj == null) {
			return;
		}

		if ((valObj instanceof JSONObject)) {
			fetchLeafKV((JSONObject) valObj, kvs);
		} else if ((valObj instanceof JSONArray)) {
			JSONArray array = (JSONArray) valObj;
			for (int i = 0; i < array.size(); i++) {
				doFetchLeafKV(key, array.get(i), kvs);
			}
		} else {
			List<String> vLst = null;
			String lKey = key;
			if (kvs.containsKey(lKey)) {
				vLst = kvs.get(lKey);
			} else {
				vLst = new LinkedList<>();
				kvs.put(lKey, vLst);
			}
			vLst.add(valObj.toString());
		}
	}

	public static void main(String[] args) throws Exception {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("expect_pay_way", 3);
		jsonObject.put("store_id", 845484);
		jsonObject.put("third_order_id", 1468463865);
		JSONArray arr = new JSONArray();
		arr.add(new Item(228, 3000));
		arr.add(new Item(88, 200));
		jsonObject.put("item", arr);
		jsonObject.put("partner_id", "partnerId1");

		JSONArray item2=new JSONArray();
		item2.add(88);
		item2.add(299);
		item2.add(100);
		jsonObject.put("item2", item2);

		// 'expect_pay_way' =>
		// int(3)
		// 'store_id' =>
		// int(845484)
		// 'third_order_id' =>
		// int(1468463865)
		// 'items' =>
		// array(1) {
		// [0] =>
		// array(2) {
		// 'ssu_id' =>
		// int(214927)
		// 'num' =>
		// int(350)
		// }
		// }
		// 'partner_id' =>
		// string(10) "partnerId1"

		System.out.println(jsonObject.toJSONString());
		String sign = gen(jsonObject, "SODEXO_SECRET");


//		JSONObject jsonObject2 = JSON.parseObject("{\"store_id\":845484,\"third_order_id\":1468463865,\"item\":[{\"num\":3000,\"ssu_id\":228},{\"num\":200,\"ssu_id\":88}],\"item2\":[88,299,100],\"partner_id\":\"partnerId1\",\"expect_pay_way\":3}");
//		String sign = gen(jsonObject2, HardCode.SODEXO_SECRET);

		System.out.println(sign);

		Thread.sleep(10);
	}

	public static class Item {
		private int ssu_id;
		private int num;

		public Item(int ssu_id, int num) {
			this.ssu_id = ssu_id;
			this.num = num;
		}

		public int getSsu_id() {
			return ssu_id;
		}

		public void setSsu_id(int ssu_id) {
			this.ssu_id = ssu_id;
		}

		public int getNum() {
			return num;
		}

		public void setNum(int num) {
			this.num = num;
		}

	}

}
